/*
 * Patient
 */
package ocp.bundles.patients.impl;

import java.util.Hashtable;
import java.util.Random;
import java.util.Vector;
import ocp.service.ContextProducer;
import ocp.service.ContextService;
import ocp.context.Attribute;
import ocp.context.AttributeDefinition;
import ocp.context.Context;
import ocp.context.ContextClass;
import ocp.context.ContextualInformation;
import ocp.context.ContextualInformationList;
import ocp.context.SimpleContext;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceRegistration;

/**
 * Clase que representa un paciente productor de contexto
 * @author Paco Lopez Marmol
 */
public class Patient implements Runnable,ContextProducer {

    private static int IDENTIFY = 0;
    
    private boolean running = false;
    private Thread thread;
    
    private String name;    // nombre
    private int id;         // identificador
    private ContextService cs = null;
    private ServiceRegistration sr;

    private synchronized static int getIdentify() {
        return ++IDENTIFY;
    }
    
    /**
     * Constructor del paciente
     * @param name nombre del paciente
     * @param bc BundleContex 
     */
    public Patient( String name , BundleContext bc ) {
        this.name = name;
        id = getIdentify();
        thread = new Thread(this);
        
        // El Paciente autoregistra el servicio de ContextProducer
        Hashtable props = new Hashtable();
        props.put("id",  name ); 
        sr = bc.registerService( ContextProducer.class.getName(), this, props );
    }

    /**
     * Obtiene el nombre del paciente
     * @return nombre del paciente
     */
    public String getName() {
        return name;
    }

    /**
     * Hilo del thread
     */
    public void run() {
        
        Context context = null;
        while (running) {
            context = updateContext();
            
            if( cs!=null )
               cs.write( context );
           
            try {
                Thread.sleep(4000);
            } catch (InterruptedException ex) {
                System.out.println( getFullId() + "interrumpido");
            }
            
        }
        
    }
    
    /**
     * Activa el thread
     */
    public void start() {
       running = true; 
       this.thread.start();   
    }
    
    /**
     * Para el thread y quita el servicio ContextProducer
     */
    public void stop()  {
        running = false;
        try {
            thread.interrupt();
            thread.join();
        } catch (InterruptedException e) {
            System.out.println( getFullId() + "interrumpido");
        }
        sr.unregister();
    }

    /**
     * Obtiene una temperatura aleatoria
     * @return temperatura
     */
    private float getRandomTemperature() {
        return (float) (36.0 + (Math.round(39 * (new Random()).nextFloat())) / 10.0);
    }

    /** 
     * Crea un contexto de tipo "Patient"
     * @return un Context con información del Paciente
     */
    private Context updateContext() {
        SimpleContext context = null;
        try {
            Hashtable h = new Hashtable();
            Attribute identifyAt = new Attribute(new AttributeDefinition("identify", Integer.class), id);
            h.put("identify", identifyAt);
            Attribute nameAt = new Attribute(new AttributeDefinition("name", String.class), name);
            h.put("name", nameAt);
            Attribute temperatureAt = new Attribute(new AttributeDefinition("temperature", Float.class), getRandomTemperature());
            h.put("temperature", temperatureAt);
            ContextualInformationList cil = new ContextualInformationList();
            context = new SimpleContext(name, "Patient-" + id);
            cil.addContextualInformation(new ContextualInformation(new ContextClass("Patient"), "Patient-" + id, "", h, new Vector()));
            context.addContextualInformationList(cil);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        
        return context;
    }

    /**
     * Activa el ContextProducer. Mensaje desde ocp para indicarnos que ya
     * podemos hacer uso del servicio ContextService.
     * @param cs Interfaz del servicio ContextService
     * @see ContextService
     */
    public void activate(ContextService cs) {
        this.cs = cs;
        System.out.println( getFullId() + "activado");
    }

    /**
     * Desactiva el ContextProducer. Mensaje desde ocp para indicarnos que el
     * servicio ocp no esta disponible.
     */
    public void deactivate() {
        cs = null;
        System.out.println( getFullId() + "desactivado");
    }

    /**
     * Obtiene el identificador del ContextProducer. 
     * @return el identificador
     */
    public String getId() {
        return new String( "" + id );
    }

    /**
     * Identificador para uso en log
     * @return el identificador 
     */
    private String getFullId() {
        return new String( "PACIENTE[" + id +"]: ");
    }
    
}
